<template>
  <div class="voice-assistant">
    <el-row :gutter="20">
      <el-col :span="16">
        <el-card class="main-card">
          <div slot="header">
            <h2>语音助手</h2>
          </div>
          <div class="assistant-content">
            <div class="conversation-area" ref="conversationArea">
              <div 
                v-for="(item, index) in conversation" 
                :key="index" 
                class="message-item"
                :class="{ 'user-message': true }"
              >
                <div class="message-info">
                  <strong>您：</strong>
                  <small>{{ formatTime(item.timestamp) }}</small>
                </div>
                <div class="message-content">{{ item.query }}</div>
              </div>
              <div 
                v-for="(item, index) in conversation" 
                :key="'response-'+index" 
                class="message-item"
                :class="{ 'assistant-message': true }"
              >
                <div class="message-info">
                  <strong>小智：</strong>
                  <small>{{ formatTime(item.timestamp) }}</small>
                </div>
                <div class="message-content">{{ item.response }}</div>
              </div>
              <div v-if="isProcessing" class="message-item assistant-message">
                <div class="message-info">
                  <strong>小智：</strong>
                </div>
                <div class="message-content processing">
                  <span>处理中</span>
                  <span class="dot">.</span>
                  <span class="dot">.</span>
                  <span class="dot">.</span>
                </div>
              </div>
              <div v-if="errorMessage" class="message-item error-message">
                <div class="message-info">
                  <strong>系统提示：</strong>
                </div>
                <div class="message-content">
                  <i class="el-icon-warning"></i> {{ errorMessage }}
                </div>
              </div>
            </div>
            
            <!-- 添加文本输入替代方案到左侧栏 -->
            <div class="text-input-area" v-if="useTextInput">
              <el-input
                v-model="textInput"
                placeholder="输入您想说的话"
                @keyup.enter.native="handleTextInput"
              >
                <el-button slot="append" icon="el-icon-s-promotion" @click="handleTextInput"></el-button>
              </el-input>
            </div>
            
            <div class="voice-control">
              <el-button 
                type="primary" 
                circle 
                icon="el-icon-microphone" 
                :class="{ 'listening': isListening, 'error': hasError }" 
                @click="toggleListening"
              ></el-button>
              <div class="status-text">
                {{ voiceStatusText }}
              </div>
              <el-button 
                v-if="!useTextInput"
                type="text" 
                size="small" 
                @click="useTextInput = true"
              >
                使用文本输入
              </el-button>
            </div>
          </div>
        </el-card>
      </el-col>
      
      <el-col :span="8">
        <el-card class="status-card">
          <div slot="header">
            <h3>智能体状态</h3>
          </div>
          <div class="agent-status">
            <el-table :data="agentStatusList" style="width: 100%">
              <el-table-column prop="name" label="智能体"></el-table-column>
              <el-table-column prop="status" label="状态">
                <template slot-scope="scope">
                  <el-tag :type="getStatusType(scope.row.status)">
                    {{ scope.row.status }}
                  </el-tag>
                </template>
              </el-table-column>
            </el-table>
          </div>
          <div class="instructions">
            <h4>使用指南：</h4>
            <p>1. 点击麦克风按钮开始监听</p>
            <p>2. 说"小智"唤醒助手</p>
            <p>3. 询问如"五月份一分公司火警次数"</p>
            <p>4. 等待小智回答</p>
          </div>
        </el-card>
        
        <!-- 添加问题排查卡片 -->
        <el-card class="troubleshoot-card" v-if="hasError">
          <div slot="header">
            <h3>无法访问麦克风？</h3>
          </div>
          <div class="troubleshoot-content">
            <p><strong>请尝试以下解决方案：</strong></p>
            <ol>
              <li>检查浏览器是否有麦克风使用权限提示，点击"允许"</li>
              <li>在浏览器设置中找到网站权限，确保此网站允许使用麦克风</li>
              <li>尝试使用Chrome或Edge浏览器</li>
              <li>检查电脑是否安装了麦克风并正常工作</li>
              <li>如使用的是HTTP链接，请尝试使用HTTPS连接访问</li>
            </ol>
            <div class="action-buttons">
              <el-button type="primary" @click="retryVoiceRecognition">重试麦克风</el-button>
              <el-button @click="useTextInput = true">使用文本输入</el-button>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import { mapState, mapActions } from 'vuex';
import voiceRecognition from '@/utils/voiceRecognition';
import VoiceSynthesis from '@/utils/voiceSynthesis';
import { voiceApi, mcpApi } from '@/api';

export default {
  name: 'VoiceAssistant',
  data() {
    return {
      voiceSynthesis: null,
      voiceStatusText: '点击麦克风按钮开始',
      errorMessage: '',
      hasError: false,
      useTextInput: false,
      textInput: '',
      apiMode: 'auto', // 'auto', 'online', 'mock'
      wakeWordActive: false
    };
  },
  computed: {
    ...mapState([
      'isListening',
      'isProcessing',
      'conversation',
      'agentStatus'
    ]),
    agentStatusList() {
      return Object.entries(this.agentStatus).map(([name, status]) => ({ name, status }));
    }
  },
  methods: {
    ...mapActions([
      'startListening',
      'stopListening',
      'processVoiceInput',
      'receiveResponse',
      'updateAgentStatus'
    ]),
    toggleListening() {
      if (this.isListening) {
        voiceRecognition.stop();
        this.stopListening();
        this.voiceStatusText = '已停止监听';
      } else {
        this.errorMessage = ''; // 清除之前的错误
        this.hasError = false;
        voiceRecognition.reset();
        voiceRecognition.start(true);
        this.startListening();
        this.voiceStatusText = '正在监听...';
      }
    },
    async processCommand(text) {
      // 处理语音命令
      this.processVoiceInput(text);
      this.voiceStatusText = '正在处理您的问题...';
      
      try {
        // 发送到API处理
        const response = await mcpApi.processIntent(text);
        
        // 语音播报结果
        this.voiceSynthesis.speak(response.answer);
        
        // 更新UI
        this.receiveResponse(response.answer);
        
        // 更新智能体状态
        if (response.agentStatus) {
          Object.entries(response.agentStatus).forEach(([name, status]) => {
            this.updateAgentStatus({ agentName: name, status });
          });
        }
        
        // 重置唤醒状态
        this.wakeWordActive = false;
        this.voiceStatusText = '处理完成，您可以说"小智"继续';
      } catch (error) {
        console.error('处理语音命令出错:', error);
        this.voiceSynthesis.speak('抱歉，处理您的请求时出现错误');
        this.receiveResponse('抱歉，处理您的请求时出现错误');
        this.voiceStatusText = '发生错误，请重试';
      }
    },
    handleVoiceError(error) {
      console.error('语音识别错误:', error);
      
      this.hasError = true;
      this.errorMessage = '语音识别出现问题，请重试或使用文本输入';
      this.voiceStatusText = '识别出错，请重试';
      this.useTextInput = true; // 自动启用文本输入
      
      this.scrollToBottom();
    },
    initVoiceTools() {
      // 初始化语音识别事件监听
      voiceRecognition.onListeningChange = (isListening) => {
        if (isListening) {
          this.startListening();
          this.voiceStatusText = '正在监听...';
        } else {
          this.stopListening();
          if (!this.wakeWordActive) {
            this.voiceStatusText = '准备就绪，请说"小智"唤醒';
          }
        }
      };
      
      voiceRecognition.onResult = (text, isFinal) => {
        console.log('语音识别结果:', text, isFinal ? '(最终)' : '(临时)');
        if (isFinal && this.wakeWordActive) {
          this.processCommand(text);
        }
      };
      
      voiceRecognition.onError = (error) => {
        console.error('语音识别错误:', error);
        // 只有在严重错误时才显示错误信息
        if (error !== 'no-speech' && error !== 'network') {
          this.hasError = true;
          this.errorMessage = '语音识别出现问题，请重试或使用文本输入';
          this.voiceStatusText = '识别出错，请重试';
          this.useTextInput = true; // 自动启用文本输入
          this.scrollToBottom();
        } else if (error === 'network') {
          // 网络错误可能是临时的，不需要停止识别
          console.warn('网络错误，继续监听...');
        }
      };
      
      voiceRecognition.onWakeWordDetected = (text) => {
        console.log('检测到唤醒词:', text);
        this.wakeWordActive = true;
        this.voiceStatusText = '已唤醒，请说出您的问题';
        // 播放唤醒提示音
        this.voiceSynthesis.speak('您好，请问有什么可以帮助您？');
      };
      
      voiceRecognition.onWakeWordTimeout = () => {
        console.log('唤醒超时');
        this.wakeWordActive = false;
        this.voiceStatusText = '唤醒超时，请说"小智"重新开始';
      };
      
      // 初始化语音合成
      this.voiceSynthesis = new VoiceSynthesis({
        lang: 'zh-CN',
        onStart: () => {
          console.log('开始播放语音');
        },
        onEnd: () => {
          console.log('语音播放结束');
        }
      });
    },
    formatTime(timestamp) {
      if (!timestamp) return '';
      const date = new Date(timestamp);
      return `${date.getHours()}:${String(date.getMinutes()).padStart(2, '0')}`;
    },
    getStatusType(status) {
      const statusMap = {
        '空闲': 'success',
        '工作中': 'primary',
        '等待': 'warning',
        '错误': 'danger'
      };
      return statusMap[status] || 'info';
    },
    scrollToBottom() {
      if (this.$refs.conversationArea) {
        this.$nextTick(() => {
          this.$refs.conversationArea.scrollTop = this.$refs.conversationArea.scrollHeight;
        });
      }
    },
    retryVoiceRecognition() {
      this.errorMessage = '';
      this.hasError = false;
      this.toggleListening();
    },
    async handleTextInput() {
      if (!this.textInput.trim()) return;
      
      const userText = this.textInput.trim();
      this.textInput = ''; // 立即清空输入框
      
      // 处理文本输入
      this.processVoiceInput(userText);
      
      try {
        // 调用API处理意图
        const response = await mcpApi.processIntent(userText);
        
        // 更新UI
        this.receiveResponse(response.answer);
        
        // 更新智能体状态
        if (response.agentStatus) {
          Object.entries(response.agentStatus).forEach(([name, status]) => {
            this.updateAgentStatus({ agentName: name, status });
          });
        }
      } catch (error) {
        console.error('处理文本命令出错:', error);
        this.receiveResponse('抱歉，处理您的请求时出现错误');
      }
      
      // 确保滚动到底部
      this.scrollToBottom();
    },
    cleanup() {
      voiceRecognition.stop();
      if (this.voiceSynthesis) {
        this.voiceSynthesis.stop();
      }
    }
  },
  mounted() {
    this.initVoiceTools();
    
    // 启动持续监听以检测唤醒词
    voiceRecognition.start(true);
    
    // 添加一些默认智能体状态
    this.updateAgentStatus({ agentName: '语音处理智能体', status: '空闲' });
    this.updateAgentStatus({ agentName: '理解智能体', status: '空闲' });
    this.updateAgentStatus({ agentName: '规划智能体', status: '空闲' });
    this.updateAgentStatus({ agentName: '知识查询智能体', status: '空闲' });
    this.updateAgentStatus({ agentName: '响应生成智能体', status: '空闲' });
    
    // 设置默认使用模拟数据模式
    this.apiMode = 'mock';
    
    // 测试API状态
    mcpApi.getAgentStatus()
      .then(response => {
        console.log('后端API连接成功', response);
        this.apiMode = 'online';
      })
      .catch(error => {
        console.warn('无法连接到后端API，将使用本地模拟数据', error);
        // 已经默认设置为mock模式，无需再设置
      });
    
    // 页面关闭前清理
    window.addEventListener('beforeunload', this.cleanup);
  },
  beforeDestroy() {
    this.cleanup();
    window.removeEventListener('beforeunload', this.cleanup);
  }
};
</script>

<style scoped>
.voice-assistant {
  max-width: 1200px;
  margin: 0 auto;
}

.main-card, .status-card {
  height: calc(100vh - 200px);
  display: flex;
  flex-direction: column;
}

.assistant-content {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.conversation-area {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
  background-color: #f5f7fa;
  border-radius: 4px;
  margin-bottom: 20px;
}

.message-item {
  margin-bottom: 15px;
  max-width: 80%;
  padding: 10px 15px;
  border-radius: 10px;
  position: relative;
}

.user-message {
  margin-left: auto;
  background-color: #ecf5ff;
  border: 1px solid #d9ecff;
}

.assistant-message {
  margin-right: auto;
  background-color: #f0f9eb;
  border: 1px solid #e1f3d8;
}

.error-message {
  background-color: #fef0f0;
  margin-right: auto;
  border-left: 4px solid #f56c6c;
  color: #f56c6c;
  width: 90%;
}

.message-info {
  display: flex;
  justify-content: space-between;
  margin-bottom: 5px;
  font-size: 12px;
}

.message-content {
  word-break: break-word;
}

.voice-control {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px 0;
}

.status-text {
  margin-left: 15px;
  color: #606266;
}

.listening {
  animation: pulse 1.5s infinite;
  background-color: #67c23a !important;
  border-color: #67c23a !important;
}

.error {
  background-color: #f56c6c !important;
  border-color: #f56c6c !important;
}

.processing .dot {
  animation: fadeInOut 1.5s infinite;
  opacity: 0;
}

.processing .dot:nth-child(2) {
  animation-delay: 0.5s;
}

.processing .dot:nth-child(3) {
  animation-delay: 1s;
}

.agent-status {
  margin-bottom: 20px;
}

.instructions {
  padding: 10px;
  background-color: #f5f7fa;
  border-radius: 4px;
}

@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(103, 194, 58, 0.4);
  }
  70% {
    box-shadow: 0 0 0 10px rgba(103, 194, 58, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(103, 194, 58, 0);
  }
}

@keyframes fadeInOut {
  0% { opacity: 0; }
  50% { opacity: 1; }
  100% { opacity: 0; }
}

.text-input-area {
  margin-bottom: 15px;
}
</style> 